package com.example.test01;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;

/**
 * 调用事件发布者
 */
@RestController
//@RequiredArgsConstructor
@Api(tags={"test"})
public class UserController {
    @Resource(name = "customThreadPool")
    private ThreadPoolTaskExecutor customThreadPool;


    @Resource(name = "stockTaskExecutor")
    private ThreadPoolTaskExecutor stockTaskExecutor;

    private static final ThreadLocal<User> threadLocalConnection = new ThreadLocal<>();


    /**
     * 测试threadlocal和线程池配合一起用 最后执行threadLocalConnection.remove();和没有执行的区别
     * 结论：必须释放，一定要有threadLocalConnection.remove();
     * 释放了才不会影响线程池中线程的复用，可以发现打印出来了重复的线程
     * 不释放，发现最大线程数10，打印的线程只有10，不会出现重复的线程
     * @return
     */
    @RequestMapping(value = "/test" )
    @ApiOperation("testThreadLocal")
    public User testThreadLocal(){
        try {
            for (int i = 0; i < 100; i++) {
                useThreadLocalWithPool();
            }
        } finally {
            customThreadPool.shutdown(); // 关闭线程池
        }
        return null;
    }

    /**
     * 测试线程池在设置核心线程数只有5，最大线程数是10，队列25的情况
     * 一次请求9次，发现剩余的四个线程走的是核心线程数
     * @return
     */
    @RequestMapping(value = "/testThreadCore" )
    @ApiOperation("testThreadCore")
    public User testThreadCore(){
        try {
            List<Future<?>> futures = new ArrayList<>();
            for (int i = 0; i < 9; i++) {
                futures.add(customThreadPool.submit(() -> useThreadLocalWithPool1()));
            }
            // 等待所有任务完成
            for (Future<?> future : futures) {
                future.get();
            }
            System.out.println("所有任务已完成");
        } catch (ExecutionException e) {
            throw new RuntimeException(e);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        } finally {
//            customThreadPool.shutdown(); // 关闭线程池
        }
        return null;
    }

    /**
     * 测试线程池在设置核心线程数只有5，最大线程数是10，队列25的情况，默认拒绝策略
     * 一次请求25次，发现核心线程和其他线程都走
     * @return
     */
    @RequestMapping(value = "/testThreadCore1" )
    @ApiOperation("testThreadCore1")
    public User testThreadCore1(){
        try {
            List<Future<?>> futures = new ArrayList<>();
            for (int i = 0; i < 25; i++) {
                futures.add(customThreadPool.submit(() -> useThreadLocalWithPool1()));
            }
            // 等待所有任务完成
            for (Future<?> future : futures) {
                future.get();
            }
            System.out.println("所有任务已完成");
        } catch (ExecutionException e) {
            throw new RuntimeException(e);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        } finally {
//            customThreadPool.shutdown(); // 关闭线程池
        }
        return null;
    }

    /**
     * 测试线程池在设置核心线程数只有5，最大线程数是10，队列25的情况，默认拒绝策略
     * 一次请求29次，重复测试几次发现会报错，因为是用的默认拒绝策略
     * @return
     */
    @RequestMapping(value = "/testThreadCore2" )
    @ApiOperation("testThreadCore2")
    public User testThreadCore2(){
        try {
            List<Future<?>> futures = new ArrayList<>();
            for (int i = 0; i < 29; i++) {
                futures.add(customThreadPool.submit(() -> useThreadLocalWithPool1()));
            }
            // 等待所有任务完成
            for (Future<?> future : futures) {
                future.get();
            }
            System.out.println("所有任务已完成");
        } catch (ExecutionException e) {
            throw new RuntimeException(e);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        } finally {
//            customThreadPool.shutdown(); // 关闭线程池
        }
        return null;
    }

    /**
     * 测试线程池在设置核心线程数只有5，最大线程数是10，队列25的情况，设置拒绝策略是CallerRunsPolicy()
     * 一次请求29次，重复测试几次发现会报错，因为是用的默认拒绝策略
     * @return
     */
    @RequestMapping(value = "/testThreadCore3" )
    @ApiOperation("testThreadCore3")
    public User testThreadCore3(){
        try {
            List<Future<?>> futures = new ArrayList<>();
            for (int i = 0; i < 29; i++) {
                futures.add(stockTaskExecutor.submit(() -> useThreadLocalWithPool1()));
            }
            // 等待所有任务完成
            for (Future<?> future : futures) {
                future.get();
            }
            System.out.println("所有任务已完成");
        } catch (ExecutionException e) {
            throw new RuntimeException(e);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        } finally {
//            customThreadPool.shutdown(); // 关闭线程池
        }
        return null;
    }



    public void useThreadLocalWithPool() {
        // 使用ThreadLocal
        customThreadPool.submit(() -> {
            User connection = getConnection();
            try {
                // 执行数据库操作
            } finally {
                // 清理ThreadLocal资源
                closeConnection();
            }
        });


    }

    public void useThreadLocalWithPool1() {
        // 使用ThreadLocal
        customThreadPool.submit(() -> {
                String name = Thread.currentThread().getName();
            long threadId = Thread.currentThread().getId();
            System.out.printf("%s - Thread ID: %d%n", name, threadId);
        });


    }
//    public void useThreadLocalWithPool2() {
//        // 使用ThreadLocal
//        stockTaskExecutor.submit(() -> {
//            String name = Thread.currentThread().getName();
//            long threadId = Thread.currentThread().getId();
//            System.out.printf("%s - Thread ID: %d%n", name, threadId);
//        });
//
//
//    }

    public  User getConnection() {
        User user = threadLocalConnection.get();
        if (user == null) {
            String name = Thread.currentThread().getName();
            System.out.println(name);
            user = new User();
            threadLocalConnection.set(user);
        }
        return user;
    }

    public static void closeConnection() {
        User connection = threadLocalConnection.get();
        if (connection != null) {
            try {
                System.out.println("1111");
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                //不能没有，切记
                threadLocalConnection.remove();
            }
        }
    }

}
